﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Reflection;
using System.ComponentModel;

namespace WPF.Controls.QuerySelector
{
   public static class Manipulation
    {
       public static string text(this FrameworkElement element)
       {
           if (element is TextBox)
           {
               return (element as TextBox).Text;
           }

           if (element is TextBlock)
           {
               return (element as TextBlock).Text;
           }
           return string.Empty;
       }

       public static FrameworkElement text(this FrameworkElement element, string text)
       {
           if (element is TextBox)
           {
               (element as TextBox).Text = text;
           }

           if (element is TextBlock)
           {
               (element as TextBlock).Text = text;
           }
           return element;
       }

       public static FrameworkElement append(this FrameworkElement element, string content)
       {
           if (element is ContentControl)
           {
               ContentControl contentControl = element as ContentControl;
               if (contentControl.Content.GetType().IsInstanceOfType(content))
               {
                   StringBuilder sb = new StringBuilder();
                   sb.Append(contentControl.Content.ToString());
                   sb.Append(content);
                   contentControl.Content = sb.ToString();
               }
           }

           if (element is TextBlock)
           {
               TextBlock contentControl = element as TextBlock;
               StringBuilder sb = new StringBuilder();
               sb.Append(contentControl.Text.ToString());
               sb.Append(content);
               contentControl.Text = sb.ToString();
           }

           return element;
       }

       public static void appendTo(this string content, FrameworkElement element)
       {
           if (element is ContentControl)
           {
               ContentControl contentControl = element as ContentControl;
               if (contentControl.Content.GetType().IsInstanceOfType(content))
               {
                   StringBuilder sb = new StringBuilder();
                   sb.Append(contentControl.Content.ToString());
                   sb.Append(content);
                   contentControl.Content = sb.ToString();
               }
           }

           if (element is TextBlock)
           {
               TextBlock contentControl = element as TextBlock;
               StringBuilder sb = new StringBuilder();
               sb.Append(contentControl.Text.ToString());
               sb.Append(content);
               contentControl.Text = sb.ToString();
           }
       }

       public static FrameworkElement prepend(this FrameworkElement element, string content)
       {
           if (element is ContentControl)
           {
               ContentControl contentControl = element as ContentControl;
               if (contentControl.Content.GetType().IsInstanceOfType(content))
               {
                   StringBuilder sb = new StringBuilder();
                   sb.Append(content);
                   sb.Append(contentControl.Content.ToString());
                   contentControl.Content = sb.ToString();
               }
           }

           if (element is TextBlock)
           {
               TextBlock contentControl = element as TextBlock;
               StringBuilder sb = new StringBuilder();
               sb.Append(content);
               sb.Append(contentControl.Text.ToString());
               contentControl.Text = sb.ToString();
           }

           return element;
       }

       public static void prependTo(this string content, FrameworkElement element)
       {
           if (element is ContentControl)
           {
               ContentControl contentControl = element as ContentControl;
               if (contentControl.Content.GetType().IsInstanceOfType(content))
               {
                   StringBuilder sb = new StringBuilder();
                   sb.Append(content);
                   sb.Append(contentControl.Content.ToString());
                   contentControl.Content = sb.ToString();
               }
           }

           if (element is TextBlock)
           {
               TextBlock contentControl = element as TextBlock;
               StringBuilder sb = new StringBuilder();
               sb.Append(content);
               sb.Append(contentControl.Text.ToString());
               contentControl.Text = sb.ToString();
           }
       }

       public static FrameworkElement after(this FrameworkElement element, object content)
       {
           Panel panel = element.Parent as Panel;
           int index=panel.Children.IndexOf(element);
           panel.Children.Insert(index+1, content as UIElement);

           return element;
       }

       public static FrameworkElement before(this FrameworkElement element, object content)
       {
           Panel panel = element.Parent as Panel;

           int index = panel.Children.IndexOf(element);
           panel.Children.Insert(index, content as UIElement);

           return element;
       }

       public static FrameworkElement insertAfter(this FrameworkElement element, object content)
       {
           Panel panel = element.Parent as Panel;
           FrameworkElement operationElement = content as FrameworkElement;
           int index = panel.Children.IndexOf(element);
           
           operationElement.remove();
           panel.Children.Insert(index, operationElement as UIElement);

           return element;
       }

       public static FrameworkElement insertBefore(this FrameworkElement element, object content)
       {
           Panel panel = element.Parent as Panel;
           if (panel != null)
           {
               FrameworkElement operationElement = content as FrameworkElement;
               int index = panel.Children.IndexOf(element);
               operationElement.remove();
               panel.Children.Insert(index - 1, content as UIElement);
           }
           
           return element;
          
       }

       public static FrameworkElement replaceWith(this FrameworkElement element, object content)
       {
           Panel panel = element.Parent as Panel;
           int index = panel.Children.IndexOf(element);
           panel.Children.Remove(element);
           panel.Children.Insert(index, content as UIElement);
           return element;
       }

       public static FrameworkElement empty(this FrameworkElement element)
       {
           if (element is ContentControl)
           {
               (element as ContentControl).ClearValue(ContentControl.ContentProperty);
               return element;
           }

           if (element.GetType().GetProperty("Text") != null)
           {
               element.GetType().GetProperty("Text").SetValue(element, string.Empty, null);
               return element;
           }

           if (element is Panel)
           {
               (element as Panel).Children.Clear();
               return element;
           }

           if (element is ItemsControl)
           {
               (element as ItemsControl).ItemsSource = null;
               (element as ItemsControl).Items.Clear();
               return element;
           }

           return element;

       }

       public static FrameworkElement remove(this FrameworkElement element)
       {
           Panel panel = element.Parent as Panel;

           panel.Children.Remove(element);
           return element;
       }
        //Inserting Around

        //wrap
       public static FrameworkElement wrap(this FrameworkElement element, FrameworkElement panel)
       {
           Panel parent = element.parent() as Panel;
           int index = element.index();
           if (panel is Decorator)
           {
               (panel as Decorator).Child = element.remove();
           }

           if (panel is ContentControl)
           {
               (panel as ContentControl).Content = element.remove();
           }
           parent.Children.Insert(index, panel);
           return element;

       }

       public static FrameworkElement wrapInner(this FrameworkElement element, FrameworkElement panel)
       {
           if (panel is Decorator)
           {
               if (element is ContentControl)
               {
                   object content=(element as ContentControl).Content;
                   (element as ContentControl).Content = null;
                   if (content is FrameworkElement)
                   {
                       (panel as Decorator).Child = content as FrameworkElement;
                       
                   }
                   else
                   {
                       (panel as Decorator).Child = new TextBlock() { Text = content.ToString() };
                   }
                   (element as ContentControl).Content = panel;
               }
               else if (element is Panel)
               {

               }
           }

           return element;
       }

       public static FrameworkElement wrapAll(this FrameworkElement element, FrameworkElement panel)
       {
           return element;
       }

       public static int index(this FrameworkElement element)
       {
           Panel panel = element.Parent as Panel;

           return panel.Children.IndexOf(element);
       }
    }
}
